<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * array flattening
 *
 * PHP version 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   Array
 * @package    Array_Flatten 
 * @author     Kazuyoshi Tlacaelel <kazu.php@gmail.com>
 * @copyright  2007 Kazuyoshi Tlacaelel
 * @license    
 * @version    CVS: $Id: Array_Flatten.class.php 69 2008-02-17 10:22:54Z kazu.php $
 * @link       
 * @see        
 * @since      
 * @deprecated 
 */

/**
 * array flattener
 *
 * converts a multi-dimensional array into a flat array
 *
 * parses every single array found within an array and extracts their 
 * information compiling a one-level-only-array trying to keep the original 
 * names of the keys found, if duplicates are found a hash will be appended to 
 * the new key to ommit overriding of values.
 * 
 * <code>
 *      // usage
 *      $x = new PEAR_Array_Flatten($array);
 *      var_export($x->getArray());
 * </code>
 *
 * @category   Array
 * @package    Array_Flatten
 * @author     Kazuyoshi Tlacaelel <kazu.php@gmail.com>
 * @copyright  2007 Kazuyoshi Tlacaelel
 * @license     PHP Version 3.0 {@link http://www.php.net/license/3_0.txt}
 */
class Array_Flatten 
{
    /**
     * contains a copy of the array to be flattened 
     *
     * @access private
     * @var array
     */
    private $array = array();

    public function __construct(Array &$array)
    {
        $this->setArray($array);
        $this->flatten();
        $array = $this->getArray();
    }

    /**
     * gets the current value of the parsed array
     *
     * @access public
     * @return array
     */
    public function getArray()
    {
        return $this->array;
    }

    /**
     * defines the array that is to be parsed by the object
     *
     * @param array $array the the array to use
     * @return void
     */
    private function setArray(&$array)
    {
        $this->array = $array;
    }

    /**
     * checks if the array to be flattened contains subarrays within
     *
     * @param array $array the array to scan for subarrays
     * @return boolean
     */
    private function _hasSubarrays($array)
    {
        foreach($array as $key => $value) {
            if (is_array($value)) {
                return true;
            }
        }
        return false;
    }

    /**
     * copies all the values of a subarray into its parent, removing subarr
     *
     * will copy all the values of a subarray defined by $array_key to its 
     * parent, once all values have been copied the sub array is deleted from 
     * its parent, if repeated keys are found a hash will be used to mantain 
     * the data.
     * 
     * @param array $array the array with subarrays
     * @param mixed $array_key $array's key containing an array
     * @return void 
     */
    private function _blendSubarray(&$array, $array_key)
    {
        $array2 = $array[$array_key];
        unset($array[$array_key]);
        foreach ($array2 as $subkey => $subvalue) {
            $key = $this->_generateUniqueKey($subkey, $array);
            $array[$key] = $subvalue;
        }
    }

    /**
     * generates a unique key that does not exist within $array trying to keep 
     * as much as possible the original key data
     *
     * @param mixed $subkey the original key to examinate
     * @param array $array the array to check for repeted keys
     * @return string a unique new key ready to be utilized
     */
    private function _generateUniqueKey($subkey, $array)
    {
        if (!array_key_exists($subkey, $array)) {
            return $subkey;
        }
        $key_chars = '';
        if (strlen($subkey) <= 3) {
            $key_chars .= $subkey; 
        } else {
            $key_chars .= $subkey[0] . $subkey[1] . $subkey[2];
        }
        $key_chars .= '_'; 
        $hash = uniqid();
        for ($i = strlen($hash); strlen($key_chars) < 10; $i --) {
            $key_chars .= $hash[$i];
        } 
        return $key_chars;
    }

    /**
     * gets all the keys of an arra which values are arrays
     *
     * @param array $array the aray to scan for arrays
     * @return array an array wich values are the keys of $array that contain 
     * arrays
     */
    private function _getSubarrayKeys($array)
    {
        $indexes_array = array();
        foreach($array as $key => $value) {
            if (is_array($value)) {
                $indexes_array[] = $key;
            }
        }
        return $indexes_array;
    }

    /**
     * makes a multi-dimensional array flat trying to keep its original keys 
     *
     * @return void
     */
    private function flatten()
    {
        $array = $this->getArray();
        while($this->_hasSubarrays($array)) {
            foreach ($this->_getSubarrayKeys($array) as $key) {
                $this->_blendSubarray($array, $key);
            }
        }
        $this->setArray($array);
    }
}

?>
